package myTeam;

import java.awt.List;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Iterator;

import robocode.AdvancedRobot;
import robocode.BulletHitEvent;
import robocode.BulletMissedEvent;
import robocode.Droid;
import robocode.HitByBulletEvent;
import robocode.HitRobotEvent;
import robocode.MessageEvent;
import robocode.Rules;
import robocode.TeamRobot;

public class Peao extends TeamRobot implements Droid {

	private int direcao = 1;

	private boolean hit;
	private boolean hasMessage = false;
	private int missCount = 0;
	private int noMessageCount = 0;
	private HashMap<String, Predicao> inimigos = new HashMap<String, Predicao>();
	private HashMap<String, Predicao> time = new HashMap<String, Predicao>();

	public void run() {

		setAdjustGunForRobotTurn(true);
		setMaxVelocity(Rules.MAX_VELOCITY);
		System.out.println(getName());
		while (true) {

			noMessageCount++;
			if (noMessageCount > 6) {
				hasMessage = false;
			}

			Predicao pre = new Predicao();
			pre = escolheInimigo();

			if (hasMessage && pre != null) {

				doMoviment(pre);

				double rotacaoArma = getGunHeadingRadians()
						- pre.absbearing(getX(), getY());
				setTurnGunLeftRadians(pre.normaliseBearingRadians(rotacaoArma));
				double distancia = pre.getDistanciaEuclidiana(getX(), getY());
				setFire(100/distancia);
				execute();
			} else {
				if (!hit) {
					setFire(0.1);
					setTurnGunRight(5);
					execute();
				} else {
					fire(3);
					execute();
				}
			}
		}
	}

	private void doMove(Predicao pre) {
		System.out.println(getName() + " moveu para " + pre.getName());
		double distancia = pre.getDistanciaEuclidiana(getX(), getY());

		if (distancia > 200) {
			double ang = getGunHeadingRadians() - getHeadingRadians();
			setTurnRightRadians(pre.normaliseBearingRadians(ang));
			setAhead(distancia / 4);
		} else {
			if (getTime() % 10 == 0) {
				double ang = getGunHeadingRadians() - getHeadingRadians()
						+ Math.PI / 2;
				turnRightRadians(pre.normaliseBearingRadians(ang));
				direcao *= -1;
			}
			ahead(direcao * 75);
		}
	}
	public void doMoviment(Predicao pre){
		double distancia = pre.getDistanciaEuclidiana(getX(), getY());
		if (distancia > 200) {
			double ang = getGunHeadingRadians() - getHeadingRadians();
			setTurnRightRadians(pre.normaliseBearingRadians(ang));
			setAhead(distancia / 4);
		} else {
		if (getTime() % 30 == 0)  { 		
			direcao *= -1;		
			setAhead(direcao * 200);
		}
		double ang = getGunHeadingRadians() - getHeadingRadians();;
		setTurnRightRadians(normaliseBearingRadians(ang + (Math.PI / 2)));
		}
	}
	public double normaliseBearingRadians(double ang) {
		if (ang > Math.PI)
			ang -= 2 * Math.PI;
		if (ang < - Math.PI)
			ang += 2 * Math.PI;
		return ang;
	}
	

	private Predicao escolheInimigo() {
		Predicao pre = null;

		ArrayList<String> list = new ArrayList<String>();
		for (String element : inimigos.keySet()) {
			Predicao p = inimigos.get(element);
			if (getTime() - p.getTurnRate() > 10) {
				list.add(element);
			} else {
				if (pre == null) {
					pre = p;
				} else {
					double ax = p.getPosXEnemy();
					double ay = p.getPosYEnemy();
					Iterator<Predicao> it = time.values().iterator();
					boolean colide = false;
					while (it.hasNext()) {
						Predicao type = (Predicao) it.next();
						double bx = type.getPosXEnemy();
						double by = type.getPosYEnemy();
						double angulo = Math.acos(ax*bx+ay*by / Math.sqrt(ax*ax + ay*ay)*Math.sqrt(bx*bx + by*by));
						if(angulo < Math.PI/4){
							colide = true;
						}

					}		
					
					double dp = p.getDistanciaEuclidiana(getX(), getY());
					if (pre.getDistanciaEuclidiana(getX(), getY()) > dp && !colide) {
						pre = p;
					}
				}
			}
		}
		for (String element : list) {
			inimigos.remove(element);
		}
		return pre;
	}

	public void onMessageReceived(MessageEvent event) {
		noMessageCount = 0;
		hasMessage = true;
		// TODO Auto-generated method stub
		System.out.println("hello");
		if (event.getMessage() instanceof Apelacao) {

		} else if (event.getMessage() instanceof RobotColors) {
			RobotColors colors = (RobotColors) event.getMessage();

			setBodyColor(colors.bodyColor);
			setGunColor(colors.gunColor);
			setRadarColor(colors.radarColor);
			setScanColor(colors.scanColor);
			setBulletColor(colors.bulletColor);

		} else if (event.getMessage() instanceof Predicao) {
			Predicao pre = (Predicao) event.getMessage();
			if (this.isTeammate(pre.getName())) {
				time.put(pre.getName(), pre);
			}else{
				inimigos.put(pre.getName(), pre);
			}
		}
	}

	public void onBulletHit(BulletHitEvent e) {
		if (hasMessage) {

		} else {
			if (hasMessage) {
				/*
				 * if(e.getName().equals("myTeam.Matatudo")){
				 * turnLeftRadians(Math.PI / 2); ahead(direcao * 100);
				 * fire(Rules.MIN_BULLET_POWER); }
				 */
			} else {
				missCount = 0;
				if (this.isTeammate(e.getName())) {
					hit = false;
				} else {
					if (this.getGunHeading() > e.getBullet().getHeading()) {
						turnGunLeft(this.getGunHeading()
								- e.getBullet().getHeading());
					} else {
						turnGunRight(e.getBullet().getHeading()
								- this.getGunHeading());
					}
					hit = true;
				}
			}
		}
	}

	public void onHitByBullet(HitByBulletEvent e) {
		if (hasMessage) {
			turnLeftRadians(Math.PI / 2);
			ahead(30);
		} else {
			if (this.isTeammate(e.getName())) {

			} else {
				if (!hit) {
					if (this.getGunHeading() > (e.getBullet().getHeading() - 180)) {
						turnGunLeft(this.getGunHeading()
								- (e.getBullet().getHeading() - 180));
					} else {
						turnGunRight((e.getBullet().getHeading() - 180)
								- this.getGunHeading());
					}
					fire(0.5);
					hit = true;
				}
			}
		}
	}

	public void onHitRobot(HitRobotEvent e) {
		if (this.isTeammate(e.getName())) {
			turnRightRadians(normaliseBearingRadians(e.getBearingRadians() +Math.PI / 2));
			ahead(30);
		} else {
			double ang = e.getBearingRadians() + (getHeadingRadians() - getGunHeadingRadians());
			turnGunRightRadians(normaliseBearingRadians(ang));
			setFire(3);
			setTurnRightRadians(normaliseBearingRadians(e.getBearing()));
			setAhead(30);
			hit = true;
		}
	}

	public void onBulletMissed(BulletMissedEvent e) {
		if (!hasMessage) {
			if (e.getBullet().getPower() > 0.1) {
				missCount++;
				if (missCount > 1) {
					hit = false;
				}
			}
		}
	}

}
